package com.jnshu.config;


import com.jnshu.constant.Constant;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * 当内部服务之间存在feign调用时，那么请求头信息会在feign请求的时候传递吗？
 * 不会，请求的头信息和请求参数都不会进行传递。
 * 但是我们可以通过通过实现RequestInterceptor接口,完成对所有的Feign请求,传递请求头和请求参数。
 * 流程：
 * getHttpServletRequest方法获取Request请求，而getHeaders从Request中拿到请求头信息，
 * 最后设置到RequestTemplate的headers中，而RequestTemplate就相当于feign客户端的HttpClient。
 *
 * 其实实现了RequestInterceptor后，直接使用@Configuration注解，不在FeignClient里面加属性也是可以的。
 */
@Slf4j
@Configuration
public class FeignWebConfigInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {
        String id = (String) getHttpServletRequest().getAttribute("id");
        try {
            requestTemplate.header(Constant.LOGINID, URLEncoder.encode(id,"UTF-8"));
        } //捕捉异常后不进行处理，否则程序无法继续执行
        catch (Exception e) {}
        log.info("FeignWebConfigInterceptor拦截器从请求头中获取到的用户id为："+id);
    }

    //获取HttpServletRequest
    private HttpServletRequest getHttpServletRequest(){
        try {
            //这种方式获取到的HttpServletRequest是线程安全的
            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        }catch (Exception e){
            return null;
        }
    }
}
